#include "VertexList.h"
#include "DAEInt.h"
#include "DAEInt2.h"
#include "DAEInt3.h"
#include "DAEInt4.h"

#include <boost/foreach.hpp>
VertexList::VertexList(int initialSize):
	m_Data(0),
	m_CurrentSize(-1),
	m_InitialSize(initialSize),
	m_CurrentCapacity(initialSize),
	m_SizePerVertex(0)
{
}

VertexList::VertexList(int initialSize, vector<SEMANTIC> semanticList, vector<int> sizeList,bool adjustCurrentSize)
: m_InitialSize(initialSize),
m_CurrentCapacity(initialSize),
m_CurrentSize(-1)
{
	
	// legacy support, assume all datatypes are floats.
	m_SizePerVertex = 0;
	vector<int>::iterator it;
	unsigned int nrOfSemantics = min(semanticList.size(),sizeList.size());
	
	for ( unsigned int i = 0; i < nrOfSemantics; ++i)
	{
		int size = sizeList[i];
		SEMANTIC semantic = semanticList[i];
		m_SizePerVertex += size*sizeof(float);

		SemanticDescriptor sd;
		sd.dataType = VL_FLOAT;
		sd.nrOfElements = size;
		sd.semantic = semantic;
		sd.index = 0;
		sd.interpolate = true;
		m_SemanticDescriptorList.push_back(sd);
	}
	m_Data = new byte[m_InitialSize*m_SizePerVertex];	
	if ( adjustCurrentSize )
		m_CurrentSize = initialSize-1;
}

VertexList::VertexList(int initialSize, vector<SemanticDescriptor> semanticList,bool adjustCurrentSize)
: m_InitialSize(initialSize),
m_CurrentCapacity(initialSize),
m_CurrentSize(-1),
m_SemanticDescriptorList(semanticList)
{
	m_SizePerVertex = 0;
	
	for ( unsigned int i = 0; i < semanticList.size(); ++i)
	{
		int size = semanticList[i].nrOfElements;
		SEMANTIC semantic = semanticList[i].semantic;
		int bytes =this->GetSizeInBytes(semanticList[i].dataType);
		m_SizePerVertex += bytes*size;
	}
	m_Data = new byte[m_InitialSize*m_SizePerVertex];	
	if ( adjustCurrentSize )
		m_CurrentSize = initialSize-1;
}

VertexList::~VertexList(void)
{
	if ( m_Data != NULL )
		delete[] m_Data;
}

void VertexList::AddSemantic(SEMANTIC semantic, int size)
{
	SemanticDescriptor sd;
		sd.dataType = VL_FLOAT;
		sd.nrOfElements = size;
		sd.semantic = semantic;
		sd.index = 0;
	m_SemanticDescriptorList.push_back(sd);
	int m_NewSizePerVertex = m_SizePerVertex + size * sizeof(float);
	byte * m_NewData = new byte[m_CurrentCapacity*m_NewSizePerVertex];
	
	if (m_Data != NULL ){
		// copy the old dat into the new data.
		byte * oldStart = m_Data;
		byte * newStart = m_NewData;
		for (int i =0; i < m_CurrentCapacity; ++i ){
			memcpy(newStart,oldStart,m_SizePerVertex);
			oldStart += m_SizePerVertex;
			newStart += m_NewSizePerVertex;
		}
		delete[] m_Data;
	}
	m_Data = m_NewData;
	m_SizePerVertex = m_NewSizePerVertex;
}

void VertexList::AddSemantic(SemanticDescriptor sd, FXValue* defaultValue)
{
	m_SemanticDescriptorList.push_back(sd);
	int addedBytes = sd.nrOfElements * GetSizeInBytes(sd.dataType);
	int m_NewSizePerVertex = m_SizePerVertex + addedBytes;
	byte * m_NewData = new byte[m_CurrentCapacity*m_NewSizePerVertex];
	 
	if ( m_Data != NULL )
	{
		byte * oldStart = m_Data;
		byte * newStart = m_NewData;
		for (int i =0; i < m_CurrentCapacity; ++i ){
			memcpy(newStart,oldStart,m_SizePerVertex);
			int bytesToCopy = min(addedBytes,defaultValue->GetSizeInBytes());
			memcpy(newStart+m_SizePerVertex,defaultValue->GetValuePointer(), bytesToCopy);
			oldStart += m_SizePerVertex;
			newStart += m_NewSizePerVertex;
		}
		delete[] m_Data;
	}
	m_Data = m_NewData;
	m_SizePerVertex = m_NewSizePerVertex;
}

void VertexList::GetVertexData(int vertexIndex, SEMANTIC semantic, FXValue* fxValue)
{
	byte* start = m_Data + this->GetOffset(vertexIndex,semantic);
	memcpy((void*)fxValue->GetValuePointer(), start, fxValue->GetSizeInBytes());
}


void VertexList::GetVertexData(int vertexIndex, int offset, FXValue* fxValue)
{
	byte* start = m_Data + vertexIndex * m_SizePerVertex + offset;
	memcpy((void*)fxValue->GetValuePointer(), start, fxValue->GetSizeInBytes());
}
	
void VertexList::AddVertexData(int vertexIndex, SEMANTIC semantic, FXValue* fxValue)
{
	byte* start = m_Data + this->GetOffset(vertexIndex, semantic);
	memcpy(start, fxValue->GetValuePointer(), fxValue->GetSizeInBytes());
}
	
void VertexList::AddVertexData(int vertexIndex, int offset, FXValue* fxValue)
{
	byte* start = m_Data + vertexIndex * m_SizePerVertex + offset;
	memcpy(start, fxValue->GetValuePointer(), fxValue->GetSizeInBytes());
}

void VertexList::AddVertexData(int vertexIndex, SEMANTIC semantic, DAEFloat4 * pVector)
{
	if (vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	byte * vertexSemantic = m_Data + this->GetOffset(vertexIndex,semantic);
	// copy 3 floats
	memcpy(vertexSemantic,pVector->GetValuePointer(),pVector->GetSizeInBytes());
	this->UpdateCurrentSize(vertexIndex);
}
void VertexList::AddVertexData(int vertexIndex, int semanticOffset, DAEFloat4 * pVector)
{
	if ( vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	byte * vertexSemantic = m_Data + vertexIndex*m_SizePerVertex + semanticOffset;
	memcpy(vertexSemantic,pVector->GetValuePointer(),pVector->GetSizeInBytes());
	this->UpdateCurrentSize(vertexIndex);
}
void VertexList::GetVertexData(int vertexIndex, SEMANTIC semantic, DAEFloat4 *pVector)
{
	float * vertexSemantic =(float*)( m_Data + this->GetOffset(vertexIndex,semantic));
	// copy 3 float
	pVector->x = vertexSemantic[0];
	pVector->y = vertexSemantic[1];
	pVector->z = vertexSemantic[2];
	pVector->w = vertexSemantic[3];
}
void VertexList::GetVertexData(int vertexIndex, int semanticOffset, DAEFloat4 *pVector)
{
	float * vertexPointer = (float*)( m_Data + vertexIndex*m_SizePerVertex + semanticOffset);
	pVector->x = vertexPointer[0];
	pVector->y = vertexPointer[1];
	pVector->z = vertexPointer[2];
	pVector->w = vertexPointer[3];
}

void VertexList::AddVertexData(int vertexIndex, SEMANTIC s, DAEFloat3 * pVector)
{
	if (vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	byte * vertexSemantic = m_Data + this->GetOffset(vertexIndex,s);
	// copy 3 floats
	memcpy(vertexSemantic,pVector->GetValuePointer(),pVector->GetSizeInBytes());
	this->UpdateCurrentSize(vertexIndex);
}

void VertexList::AddVertexData(int vertexIndex, int semanticOffset, DAEFloat3 * pVector)
{
	if ( vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	byte * vertexSemantic = m_Data + vertexIndex*m_SizePerVertex + semanticOffset;
	memcpy(vertexSemantic,pVector->GetValuePointer(),pVector->GetSizeInBytes());
	this->UpdateCurrentSize(vertexIndex);

}
	
void VertexList::GetVertexData(int vertexIndex, SEMANTIC s, DAEFloat3 *pVector)
{
	float * vertexSemantic = (float*)(m_Data + this->GetOffset(vertexIndex,s));
	// copy 3 float
	pVector->x = vertexSemantic[0];
	pVector->y = vertexSemantic[1];
	pVector->z = vertexSemantic[2];
}

void VertexList::GetVertexData(int vertexIndex, int semanticOffset, DAEFloat3 *pVector)
{
	float * vertexPointer = (float*)( m_Data + vertexIndex*m_SizePerVertex + semanticOffset);
	pVector->x = vertexPointer[0];
	pVector->y = vertexPointer[1];
	pVector->z = vertexPointer[2];
}

void VertexList::GetVertexData(int vertexIndex, int semanticOffset, DAEFloat2 *pVector)
{
	float * vertexSemantic = (float*)(m_Data + vertexIndex*m_SizePerVertex + semanticOffset);
	// copy 2 float
	pVector->x = vertexSemantic[0];
	pVector->y = vertexSemantic[1];
}


void VertexList::AddVertexData(int vertexIndex, SEMANTIC s, DAEFloat2 * pVector)
{
	if (vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	byte * vertexSemantic = m_Data + this->GetOffset(vertexIndex,s);
	// copy 2 floats
	memcpy(vertexSemantic,pVector->GetValuePointer(),pVector->GetSizeInBytes());
	this->UpdateCurrentSize(vertexIndex);
}

void VertexList::AddVertexData(int vertexIndex, int semanticOffset, DAEFloat2 * pVector)
{
	if (vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	byte * vertexSemantic = m_Data + vertexIndex*m_SizePerVertex +semanticOffset;
	// copy 2 floats
	memcpy(vertexSemantic,pVector->GetValuePointer(),pVector->GetSizeInBytes());
	this->UpdateCurrentSize(vertexIndex);
}

void VertexList::GetVertexData(int vertexIndex, SEMANTIC s, DAEFloat2 *pVector)
{	
	float * vertexSemantic = (float*)(m_Data + this->GetOffset(vertexIndex,s));
	// copy 2 floats
	pVector->x = vertexSemantic[0];
	pVector->y = vertexSemantic[1];
}



void VertexList::AddVertexData(int vertexIndex, SEMANTIC s, float value)
{
	if (vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	float * vertexSemantic = (float*)(m_Data + this->GetOffset(vertexIndex,s));
	*vertexSemantic = value;
}

void VertexList::AddVertexData(int vertexIndex, int semanticOffset, float value)
{
	if (vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	float * vertexSemantic = (float*)(m_Data + vertexIndex * m_SizePerVertex + semanticOffset);
	*vertexSemantic = value;
}
	
float VertexList::GetVertexData(int vertexIndex, SEMANTIC s)
{
	float * vertexSemantic = (float*)(m_Data + this->GetOffset(vertexIndex,s));
	return *vertexSemantic;
}

float VertexList::GetVertexData(int vertexIndex, int semanticOffset)
{
	float * vertexSemantic = (float*)(m_Data + vertexIndex*m_SizePerVertex+semanticOffset);
	return *vertexSemantic;
}

void VertexList::AddVertexData(int vertexIndex, SEMANTIC s,float * dataPtr, int size)
{
	if (vertexIndex >= m_CurrentCapacity)
		Grow(m_CurrentCapacity*2);
	byte * vertexSemantic = m_Data + this->GetOffset(vertexIndex,s);
	memcpy(vertexSemantic,dataPtr,size*sizeof(float));
	this->UpdateCurrentSize(vertexIndex);
}

void VertexList::GetVertexData(int vertexIndex, SEMANTIC s, float * dataPtr, int size)
{
	byte * vertexSemantic = m_Data + this->GetOffset(vertexIndex,s);
	memcpy(dataPtr,vertexSemantic,size*sizeof(float));
}

void VertexList::NormalizeDataBySemantic(SEMANTIC s)
{
	int offset = this->GetOffset(s);
	if (offset < 0)
		return;
	int size = this->GetSize();
	int semanticSize = this->GetSemanticSize(s);
	float * start = (float*)(m_Data+offset);
	switch(semanticSize){
		case 2:
			for (int i = 0; i < size; i++)
			{
				DAEFloat2* toNormalize = (DAEFloat2*)start;
				toNormalize->Normalize();
				start += m_SizePerVertex;
			}
			break;
		case 3:
			for (int i = 0; i < size; i++)
			{
				DAEFloat3* toNormalize = (DAEFloat3*)start;
				toNormalize->Normalize();
				start += m_SizePerVertex;
			}
			break;
	}	
}

void VertexList::TransformVertexSemantic(DAEMatrix& matrix,SEMANTIC s)
{
	int offset= this->GetOffset(s);
	if ( offset < 0 )
		return;
	int size = this->GetSize();
	int semanticSize = this->GetSemanticSize(s);
	float * start = (float*)( m_Data+offset);
	if ( semanticSize == 3)
	{
		for ( int i = 0 ; i < size ; i++ ){
			DAEFloat3* toTransform = (DAEFloat3*)start;
			matrix.TransformVector(*toTransform,*toTransform);
			start += m_SizePerVertex;
		}
	}
}

void VertexList::FillSemantic(SEMANTIC s,DAEFloat3* fillValue)
{
	int offset = this->GetOffset(s);
	if (offset<0)
		return;
	int semanticSize = this->GetSemanticSize(s);
	if (semanticSize != 3)
		return;
	byte* start = m_Data+offset;
	for ( int i=0;i< m_CurrentCapacity;i++)
	{
		memcpy(start,fillValue->GetValuePointer(),fillValue->GetSizeInBytes());
		start += m_SizePerVertex;
	}
}

void VertexList::FillSemantic(SEMANTIC s,FXValue* fillValue)
{
	int offset = this->GetOffset(s);
	if (offset<0)
		return;
	
	byte* start = m_Data+offset;
	for ( int i=0;i< m_CurrentCapacity;i++)
	{
		memcpy(start,fillValue->GetValuePointer(),fillValue->GetSizeInBytes());
		start += m_SizePerVertex;
	}
}

void VertexList::AddNormalForTri(int v1, int v2, int v3)
{
	int posOffset = this->GetOffset(POSITION);
	int normalOffset = this->GetOffset(NORMAL);
	this->AddNormalForTri(posOffset,normalOffset,v1,v2,v3);
}

void VertexList::AddNormalForTri(int posOffset, int normalOffset, int v1, int v2, int v3)
{
	DAEFloat3 first(0,0,0);
	this->GetVertexData(v1, posOffset, &first);
	DAEFloat3 second(0,0,0);
	this->GetVertexData(v2, posOffset, &second);
	DAEFloat3 third(0,0,0);
	this->GetVertexData(v3, posOffset, &third);
	DAEFloat3 axis1;
	second.Subtract(axis1,first);
	DAEFloat3 axis2; 
	third.Subtract(axis2,first);
	DAEFloat3 normal;
	axis1.CrossAndNormalize(normal,axis2);
	
	// current normal
	DAEFloat3 normal1, normal2, normal3;
	
	this->GetVertexData(v1, normalOffset, &normal1);
	this->GetVertexData(v2, normalOffset, &normal2);
	this->GetVertexData(v3, normalOffset, &normal3);
	
	normal1.Add(normal1,normal);
	normal2.Add(normal2,normal);
	normal3.Add(normal3,normal);

	this->AddVertexData(v1, normalOffset, &normal1);
	this->AddVertexData(v2, normalOffset, &normal2);
	this->AddVertexData(v3, normalOffset, &normal3);
}

void VertexList::Grow(int newCapacity)
{
	if ( newCapacity == 0 )
		newCapacity = 2;
	byte * pData = new byte[newCapacity* m_SizePerVertex];
	memcpy(pData, m_Data, m_CurrentCapacity * m_SizePerVertex);
	delete[]  m_Data;
	m_Data = pData;
	m_CurrentCapacity = newCapacity;
}

int VertexList::GetOffset(int vertexIndex,SEMANTIC s)
{
	return vertexIndex * m_SizePerVertex+GetOffset(s);
}

int VertexList::GetOffset(SEMANTIC s)
{
	vector<SemanticDescriptor>::const_iterator semanticIt;
	int offset = 0;
	for ( semanticIt = m_SemanticDescriptorList.begin();semanticIt != m_SemanticDescriptorList.end();semanticIt++)
	{	
		SemanticDescriptor sd = *semanticIt;
		if ( sd.semantic == s )
			return offset;

		offset+= GetSizeInBytes(sd.dataType)*sd.nrOfElements;
	}
	// no semantic was found so return -1
	return -1;
}

int VertexList::GetSizeInBytes(DATATYPE dataType)
{
	switch( dataType ){
		case VL_FLOAT:
		case VL_SINT:
		case VL_UINT: return 4;break;
		case VL_SSHORT:
		case VL_USHORT: return 2;break;
		case VL_SBYTE:
		case VL_UBYTE: return 1;break;
		}
	return 0;
}

int VertexList::GetSemanticSize(SEMANTIC s){
	vector<SemanticDescriptor>::const_iterator semanticIt;
	
	for ( semanticIt = m_SemanticDescriptorList.begin();semanticIt != m_SemanticDescriptorList.end();semanticIt++)
	{	
		SemanticDescriptor sd = *semanticIt;	
		if ( sd.semantic == s )
			return sd.nrOfElements;
	}
	return 0;
}

void VertexList::UpdateCurrentSize(int index){
	if (index>m_CurrentSize)
		m_CurrentSize = index;
}

int VertexList::GetSize(){
	return m_CurrentSize + 1;
}


SEMANTIC VertexList::GetSemantic(unsigned int index)
{
	if (index < m_SemanticDescriptorList.size() )
		return m_SemanticDescriptorList[index].semantic;
	else
		return POSITION;
}

int VertexList::GetSemanticSize(unsigned int index)
{
	if (index < m_SemanticDescriptorList.size() )
		return m_SemanticDescriptorList[index].nrOfElements;
	else
		return 0;
}

DATATYPE VertexList::GetSemanticDataType(unsigned int index){
	if (index < m_SemanticDescriptorList.size() )
		return m_SemanticDescriptorList[index].dataType;
	else
		return VL_FLOAT;
}


VertexList* VertexList::Create3DPosVL(int initialSize)
{
	vector<SemanticDescriptor> descriptors;
	SemanticDescriptor pos;
	pos.semantic = POSITION;
	pos.dataType = VL_FLOAT;
	pos.index = 0;
	pos.nrOfElements = 3;
	descriptors.push_back(pos);
	return new VertexList(initialSize,descriptors);
}

VertexList* VertexList::Create3DPosColorVL(int initialSize)
{
	vector<SemanticDescriptor> descriptors;
	SemanticDescriptor pos;
	pos.semantic = POSITION;
	pos.dataType = VL_FLOAT;
	pos.index = 0;
	pos.nrOfElements = 3;

	SemanticDescriptor color;
	color.semantic = COLOR;
	color.dataType = VL_FLOAT;
	color.index = 0;
	color.nrOfElements = 3;

	descriptors.push_back(pos);
	descriptors.push_back(color);
	return new VertexList(initialSize,descriptors);
}

VertexList* VertexList::Create3DPosTexVL(int initialSize)
{
	vector<SemanticDescriptor> descriptors;
	SemanticDescriptor pos;
	pos.semantic = POSITION;
	pos.dataType = VL_FLOAT;
	pos.index = 0;
	pos.nrOfElements = 3;

	SemanticDescriptor tc;
	tc.semantic = TEXCOORD;
	tc.dataType = VL_FLOAT;
	tc.index = 0;
	tc.nrOfElements = 2;

	descriptors.push_back(pos);
	descriptors.push_back(tc);
	return new VertexList(initialSize,descriptors);
}

VertexList* VertexList::Create3DPosTexNormalVL(int initialSize)
{
	vector<SemanticDescriptor> descriptors;
	SemanticDescriptor pos;
	pos.semantic = POSITION;
	pos.dataType = VL_FLOAT;
	pos.index = 0;
	pos.nrOfElements = 3;

	SemanticDescriptor tc;
	tc.semantic = TEXCOORD;
	tc.dataType = VL_FLOAT;
	tc.index = 0;
	tc.nrOfElements = 2;


	SemanticDescriptor normal;
	normal.semantic = NORMAL;
	normal.dataType = VL_FLOAT;
	normal.index = 0;
	normal.nrOfElements = 2;

	descriptors.push_back(pos);
	descriptors.push_back(tc);
	descriptors.push_back(normal);
	return new VertexList(initialSize,descriptors);
}

int VertexList::AddInterpolatedVertex(int index1, int index2, float t )
{
	if ( index1 > m_CurrentSize || index2 > m_CurrentSize)
	{
		return -1;
	}else{
		int newIndex = this->m_CurrentSize+1;
		BOOST_FOREACH(SemanticDescriptor& sd, m_SemanticDescriptorList)
		{
			int offset = this->GetOffset(sd.semantic);
			
			switch(sd.dataType)
			{
				case VL_FLOAT:AddInterpolatedFloatVertex(newIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,t);break;
				case VL_SINT:AddInterpolatedSignedIntVertex(newIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,t);break;
				case VL_SSHORT:AddInterpolatedSignedShortVertex(newIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,t);break;
				case VL_SBYTE:AddInterpolatedSignedByteVertex(newIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,t);break;
				case VL_UINT:AddInterpolatedUnsignedIntVertex(newIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,t);break;
				case VL_USHORT:AddInterpolatedUnsignedShortVertex(newIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,t);break;
				case VL_UBYTE:AddInterpolatedUnsignedByteVertex(newIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,t);break;
			}
		}
		return newIndex;
	}
}

void VertexList::AddInterpolatedFloatVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,float t)
{
	if ( nrOfElements == 1 ){
		float value1 = GetVertexData(index1,offset);
		float value2 = GetVertexData(index2,offset);
		if ( interpolate ){
			float newValue = value1 + t*(value2-value1);
			AddVertexData(index,offset,value1);
		}else{
			AddVertexData(index,offset,value1);
		}
	}
	else if ( nrOfElements == 2 )
	{
		DAEFloat2 value1,value2;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		if ( interpolate )
		{
			DAEFloat2 newValue;
			newValue.x = value1.x + t*(value2.x-value1.x);
			newValue.y = value1.y + t*(value2.y-value1.y);
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
	else if ( nrOfElements == 3 ){
		DAEFloat3 value1,value2;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		if ( interpolate )
		{
			DAEFloat3 newValue;
			newValue.x = value1.x + t*(value2.x-value1.x);
			newValue.y = value1.y + t*(value2.y-value1.y);
			newValue.z = value1.z + t*(value2.z-value1.z);
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
	else if ( nrOfElements == 4 ){
		DAEFloat4 value1,value2;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		if ( interpolate )
		{
			DAEFloat4 newValue;
			newValue.x = value1.x + t*(value2.x-value1.x);
			newValue.y = value1.y + t*(value2.y-value1.y);
			newValue.z = value1.y + t*(value2.z-value1.z);
			newValue.w = value1.y + t*(value2.w-value1.w);
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
}
void VertexList::AddInterpolatedSignedIntVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,float t)
{
	if ( nrOfElements == 1 ){
		DAEInt value1,value2;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value1);
		if ( interpolate ){
			DAEInt result;
			result.x = value1.x + (int)(t*(value2.x-value1.x));
			AddVertexData(index,offset,&result);
		}else{
			AddVertexData(index,offset,&value1);
		}
	}
	else if ( nrOfElements == 2 )
	{
		DAEInt2 value1,value2;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		if ( interpolate )
		{
			DAEInt2 newValue;
			newValue.x = value1.x + (int)(t*(value2.x-value1.x));
			newValue.y = value1.y + (int)(t*(value2.y-value1.y));
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
	else if ( nrOfElements == 3 ){
		DAEInt3 value1,value2;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		if ( interpolate )
		{
			DAEInt3 newValue;
			newValue.x = value1.x + (int)(t*(value2.x-value1.x));
			newValue.y = value1.y + (int)(t*(value2.y-value1.y));
			newValue.z = value1.y + (int)(t*(value2.z-value1.z));
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
	else if ( nrOfElements == 4 ){
		DAEInt4 value1,value2;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		if ( interpolate )
		{
			DAEInt4 newValue;
			newValue.x = value1.x + (int)(t*(value2.x-value1.x));
			newValue.y = value1.y + (int)(t*(value2.y-value1.y));
			newValue.z = value1.y + (int)(t*(value2.z-value1.z));
			newValue.w = value1.y + (int)(t*(value2.w-value1.w));
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
}
void VertexList::AddInterpolatedSignedShortVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,float t)
{
}
void VertexList::AddInterpolatedSignedByteVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,float t)
{
}
void VertexList::AddInterpolatedUnsignedIntVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,float t)
{
}
void VertexList::AddInterpolatedUnsignedShortVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,float t)
{
}
void VertexList::AddInterpolatedUnsignedByteVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,float t)
{
}

int VertexList::AddInterpolatedVertex(int index1, int index2, int index3, float l1, float l2, float l3)
{
	if ( index1 > m_CurrentSize || index2 > m_CurrentSize)
	{
		return -1;
	}else{
		int newIndex = this->m_CurrentSize+1;
		SetInterpolatedVertex(newIndex,index1,index2,index3,l1,l2,l3);
		return newIndex;
	}
}

void VertexList::SetInterpolatedVertex(int vertexIndex,int index1, int index2, int index3, float l1, float l2, float l3)
{
		BOOST_FOREACH(SemanticDescriptor& sd, m_SemanticDescriptorList)
		{
			int offset = this->GetOffset(sd.semantic);
			
			switch(sd.dataType)
			{
				case VL_FLOAT:AddInterpolatedFloatVertex(vertexIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,index3, l1,l2,l3);break;
				case VL_SINT:AddInterpolatedSignedIntVertex(vertexIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,index3, l1,l2,l3);break;
				case VL_SSHORT:AddInterpolatedSignedShortVertex(vertexIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,index3, l1,l2,l3);break;
				case VL_SBYTE:AddInterpolatedSignedByteVertex(vertexIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,index3, l1,l2,l3);break;
				case VL_UINT:AddInterpolatedUnsignedIntVertex(vertexIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,index3, l1,l2,l3);break;
				case VL_USHORT:AddInterpolatedUnsignedShortVertex(vertexIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,index3, l1,l2,l3);break;
				case VL_UBYTE:AddInterpolatedUnsignedByteVertex(vertexIndex,offset,sd.nrOfElements,sd.interpolate,index1,index2,index3, l1,l2,l3);break;
			}
		}
}

void VertexList::AddInterpolatedFloatVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,int index3, float l1, float l2, float l3)
{
	if ( nrOfElements == 1 ){
		float value1 = GetVertexData(index1,offset);
		float value2 = GetVertexData(index2,offset);
		float value3 = GetVertexData(index3,offset);
		if ( interpolate ){
			float newValue = l1* value1 + l2*value2 + l3*value3;
			AddVertexData(index,offset,value1);
		}else{
			AddVertexData(index,offset,value1);
		}
	}
	else if ( nrOfElements == 2 )
	{
		DAEFloat2 value1,value2,value3;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		GetVertexData(index3,offset,&value3);
		if ( interpolate )
		{
			DAEFloat2 newValue;
			newValue.x = l1* value1.x + l2*value2.x + l3* value3.x;
			newValue.y = l1* value1.y + l2*value2.y + l3* value3.y;
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
	else if ( nrOfElements == 3 ){
		DAEFloat3 value1,value2,value3;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		GetVertexData(index3,offset,&value3);
		if ( interpolate )
		{
			DAEFloat3 newValue;
			newValue.x = l1* value1.x + l2*value2.x + l3* value3.x;
			newValue.y = l1* value1.y + l2*value2.y + l3* value3.y;
			newValue.z = l1* value1.z + l2*value2.z + l3* value3.z;
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
	else if ( nrOfElements == 4 ){
		DAEFloat4 value1,value2,value3;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		GetVertexData(index3,offset,&value2);
		if ( interpolate )
		{
			DAEFloat4 newValue;
			newValue.x = l1* value1.x + l2*value2.x + l3* value3.x;
			newValue.y = l1* value1.y + l2*value2.y + l3* value3.y;
			newValue.z = l1* value1.z + l2*value2.z + l3* value3.z;
			newValue.w = l1* value1.w + l2*value2.w + l3* value3.w;
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
}

void VertexList::AddInterpolatedSignedIntVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,int index3, float l1, float l2, float l3)
{
	if ( nrOfElements == 1 ){
		DAEInt value1,value2,value3;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		GetVertexData(index3,offset,&value3);
		if ( interpolate ){
			DAEInt newValue;
			newValue.x = (int)(l1* value1.x + l2*value2.x + l3*value3.x);
			AddVertexData(index,offset,&newValue);
		}else{
			AddVertexData(index,offset,&value1);
		}
	}
	else if ( nrOfElements == 2 )
	{
		DAEInt2 value1,value2,value3;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		GetVertexData(index3,offset,&value3);
		if ( interpolate )
		{
			DAEInt2 newValue;
			newValue.x = (int)(l1* value1.x + l2*value2.x + l3* value3.x);
			newValue.y = (int)(l1* value1.y + l2*value2.y + l3* value3.y);
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
	else if ( nrOfElements == 3 ){
		DAEInt3 value1,value2,value3;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		GetVertexData(index3,offset,&value3);
		if ( interpolate )
		{
			DAEInt3 newValue;
			newValue.x = (int)(l1* value1.x + l2*value2.x + l3* value3.x);
			newValue.y = (int)(l1* value1.y + l2*value2.y + l3* value3.y);
			newValue.z = (int)(l1* value1.z + l2*value2.z + l3* value3.z);
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
	else if ( nrOfElements == 4 ){
		DAEInt4 value1,value2,value3;
		GetVertexData(index1,offset,&value1);
		GetVertexData(index2,offset,&value2);
		GetVertexData(index3,offset,&value2);
		if ( interpolate )
		{
			DAEInt4 newValue;
			newValue.x = (int)(l1* value1.x + l2*value2.x + l3* value3.x);
			newValue.y = (int)(l1* value1.y + l2*value2.y + l3* value3.y);
			newValue.z = (int)(l1* value1.z + l2*value2.z + l3* value3.z);
			newValue.w = (int)(l1* value1.w + l2*value2.w + l3* value3.w);
			AddVertexData(index,offset,&newValue);
		}else
			AddVertexData(index,offset,&value1);
	}
}
	
void VertexList::AddInterpolatedSignedShortVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,int index3, float l1, float l2, float l3)
{
}
	
void VertexList::AddInterpolatedSignedByteVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,int index3, float l1, float l2, float l3)
{
}
	
void VertexList::AddInterpolatedUnsignedIntVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,int index3, float l1, float l2, float l3)
{
}
	
void VertexList::AddInterpolatedUnsignedShortVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,int index3, float l1, float l2, float l3)
{
}
	
void VertexList::AddInterpolatedUnsignedByteVertex(int index, int offset, int nrOfElements,bool interpolate,int index1,int index2,int index3, float l1, float l2, float l3)	
{
}
